<!DOCTYPE html>
<meta charset="utf-8">
<link rel='stylesheet' href="{{ url_for('static', filename='css/style.css') }}" type='text/css' media='all' />
<head>

 <style type="text/css">
		.tooltip{
			font-family:simsun;
			font-size:16px;
			width:120;
			height:auto;
			position:absolute;
			text-align:center;
			border-style:solid;
			border-width:1px;
			background-color:white;
			border-radius:5px;
		}
 
</style>

</head>
<body>

<div width="100%">
<table><tr><td>
  <svg width="100%" height="100%"></svg>
</td><td>
  <div class="infobox" id="infobox" >
      CLICK ON DEVICE FOR NEIGHBOR/INTERFACE INFORMATION
  </div>
  <div class="infobox2" id="infobox2" >
  </div>
  <div class="infobox3" id="infobox3" >
  </div>
  <div>
	<button type="button" id="checkpathBT" onclick="inputTwoDevices();">Check Path</button>
  </div>
  <div>
	<button type="button" id="streamregister" onclick="registerstream();">Register Stream</button>
  </div>
</td></tr></table >
</div>

</body>
<script src="static/d3.v4.min.js"></script>
<script src="static/jquery.min.js"></script>

<script>
function LoadconfigdeviceHTML(n, i, p)
{
	window.location.replace('/configdeviceHTML?name='+n+'&ip='+i+'&port='+p);
}

function LoadconfigstreamHTML(s)
{
	window.location.replace('/configstreamHTML?sid='+s);
}

var streamsetshow =  '<form id="formSetStream"> \
	<br>Path Select: \
	<select class="button device" id="pathselect" name="pathselect"> \
	</select> \
	<br>VLAN ID:&nbsp;&nbsp; \
	<input type="text" id="vid" name="vid" value=""> \
	<br>Stream ID:&nbsp; \
	<input type="text" id="sid" name="sid" value=""> \
	<br>Priority:&nbsp; \
	<input type="text" id="priority" name="priority" value=""> \
	<input type="button" id="add" value="Add" onclick="streamadd()"> \
	</form>';

function registerstream() {
	$("#streamregister").after(streamsetshow);
	$.ajax({
		type:"GET",
		url: "/topology/getstreampaths",
		dataType: "json",
		contentType: "application/json; charset=utf-8",
		success: function (data) {
			console.log("========GET PATH=====");
			for (var i in data) {
				$("#pathselect").append("<option value=" + i + ">" + data[i] + "</option>");
			}
		}
	});
}

function streamadd() {
	var stream = {};

	stream["pathid"] = $("#pathselect").val();
	var sid = $("input[name='sid']").val();
	if (sid != '') {
		stream["streamid"] = sid;
		if (isNaN(parseInt(sid))) {
			alert("stream ID Error!");
			return;
		}
	}

	var vid = $("input[name='vid']").val();
	if (vid != '') {
		stream["vid"] = vid;
		if (isNaN(parseInt(vid))) {
			alert("VLAN ID Error!");
			return;
		}
	}

	var priority = $("input[name='priority']").val();
	if (priority != '') {
		stream["priority"] = priority;
		if (isNaN(parseInt(priority))) {
			alert("priority Error!");
			return;
		}
	}

	$.ajax({
		type: "POST",
		url: "/topology/streamregister",
		dataType: "json",
		contentType: "application/json; charset=utf-8",
		data: JSON.stringify(stream),
		success: function(data){
			if (data.status == 'false')
				alert('Feedback ERROR!');
			text = tableFromStream(data);
			printToDivWithID("infobox3","<font color=\"red\">Stream List:</font><br>" + text);
		}
	});
	$("#formSetStream").remove();
}

function tableFromStream(data){
  text = "<table class=\"infobox3\" table border='1' cellspacing='0'>";
  text+= "<thead><th><u><h4>STREAM ID</h4></u></th><th><u><h4>VLAN ID</h4></u></th><th><u><h4>PRIORITY</h4></u></th>";
  text+= "</thead>";

  for (var sid in data) {
    text+= "<tr>";
    text+= "<td><a href=\"javascript:LoadconfigstreamHTML('"+sid+"');\">" + sid + "</td>";
    text+= "<td>" + data[sid]['vid'] + "</td>";
    text+= "<td>" + data[sid]['priority'] + "</td>";
    text+= "</tr>";
  }

  text+= "</table>";

  return text;
}

var focusinput = undefined;

var formshow = '<form id="formGetPath"> \
	First Device:<br> \
	<input type="text" id="firstname" name="firstname" value=""> \
	<br> \
	Second Device:<br> \
	<input type="text" id="secondname" name="secondname" value=""> \
	<br><br> \
	<input type="button" id="summit" value="Submit" onclick="getpath()"> \
	</form>';

function inputTwoDevices() {
	$("#checkpathBT").after(formshow);

        $("#firstname").focus(function(){
		focusinput = "#firstname";
		console.log(focusinput);
        });
        $("#firstname").blur(function(){
		console.log(focusinput);
        });
        $("#secondname").focus(function(){
		focusinput = "#secondname";
		console.log(focusinput);
        });
        $("#secondname").blur(function(){
		console.log(focusinput);
        });

	//for (var m in oldgraph.links) {
	//	oldgraph.links[m].value = pathlist[m];
	//}

}

var pathlist = new Array();

function getpath() {
	pathlist = [];
	console.log("getpath form summit button pressed");
	source = $("#firstname").val();
	target = $("#secondname").val();
	if (source.length == 0 || target.length == 0) {
		alert("select source and target");
		return;
	}

    $.ajax({
	type:"GET",
	url: "/topology/getpath",
	dataType: "json",
	data: {'source':source, 'target':target},
	contentType: "application/json; charset=utf-8",
	success: function (data) {
		console.log("========GET PATH=====");
		pathd = data.path.substring(1, data.path.length -1);
		console.log(pathd);
		pathing = pathd.split(",");
		if (pathing.length == 0)
			return;
		for (var j in pathing){
			console.log(pathing[j]);
			var ret = $.trim(pathing[j]);
			pathing[j] = ret.substring(1, ret.length -1);
		}
		for (var i = 0; i < (pathing.length - 1); i++) {
			for (var k in oldgraph.links) {
				//pathlist.push(oldgraph.links[k].value);
				if ((oldgraph.links[k].source.id == pathing[i] &&
				     oldgraph.links[k].target.id == pathing[i + 1]) ||
				    (oldgraph.links[k].source.id == pathing[i + 1] &&
				     oldgraph.links[k].target.id == pathing[i])) {
					oldgraph.links[k].value = 30;
				}
			}

		}
		console.log(pathlist);
		//alert(JSON.stringify(data.path));
		console.log("=====================");
	}
	});
	$("#formGetPath").remove();
	focusinput = undefined;
}

// =============================
// PRINTING DEVICE DETAILS TABLE
// =============================

// ====================
// READING OF JSON FILE
// ====================
function readTextFile(file, deviceid, callback) {
    var rawFile = new XMLHttpRequest();
    rawFile.overrideMimeType("application/json");
    rawFile.open("GET", file+"?device="+deviceid, true);
    rawFile.onreadystatechange = function() {
        if (rawFile.readyState === 4 && rawFile.status == "200") {
            callback(rawFile.responseText);
        }
    }
    rawFile.send(null);
}

function OnClickDetails(deviceid){
  //alert("devicedetails: " + deviceid);
  //usage:

	var $focused = $(':focus');
	if (focusinput != undefined) {
		console.log($(focusinput));
		$(focusinput).val(deviceid);
	}
  // #############################
  // # READING NEIGHBORS         #
  // #############################
  readTextFile("topology/neighborships.json", deviceid, function(text){
      var data = JSON.parse(text);
      console.log(data);
      console.log(deviceid);

      bFoundMatch = 0;
      for (var key in data) {
        console.log("Key: " + key + " vs " + deviceid);

        if ((deviceid.localeCompare(key)) == 0){
          console.log("match!");
          bFoundMatch = 1;
          text = tableFromNeighbor(key,data);

	  printToDivWithID("infobox","<h2><u>" + key + "</u></h2>" + text);
        }
      }
      if (!(bFoundMatch)){
        warning_text = "<h4>The selected device id: ";
        warning_text+= deviceid;
        warning_text+= " is not in database!</h4>";
        warning_text+= "This is most probably as you clicked on edge node ";
        warning_text+= "that is not NETCONF data gathered, try clicking on its neighbors.";
        printToDivWithID("infobox",warning_text);
      }
  });

  // ####################################
  // # READING NEIGHBOR-LESS INTERFACES #
  // ####################################
  readTextFile("topology/no_neighbor_interfaces.json", deviceid, function(text){
      var data = JSON.parse(text);
      console.log(data);
      console.log(deviceid);

      bFoundMatch = 0;
      for (var key in data) {
        console.log("Key: " + key + " vs " + deviceid);

        if ((deviceid.localeCompare(key)) == 0){
          console.log("match!");
          bFoundMatch = 1;
          text = tableFromUnusedInterfaces(key,data);
          printToDivWithID("infobox2","<font color=\"red\">Enabled Interfaces without LLDP Neighbor:</font><br>" + text);
        }
      }
      if (!(bFoundMatch)){
        printToDivWithID("infobox2","");
      }
  });
}

// ####################################
// # using input parameters returns
// # HTML table with these inputs
// ####################################
function tableFromUnusedInterfaces(key,data){
  text = "<table class=\"infobox2\">";
  text+= "<thead><th><u><h4>LOCAL INT.</h4></u></th><th><u><h4>DESCRIPTION</h4></u></th><th><u><h4>Bandwith</h4></u></th>";
  text+= "</thead>";

  for (var neighbor in data[key]) {
    text+= "<tr>";

    console.log("local_intf:" + data[key][neighbor]['local_intf']);
    text+= "<td>" + data[key][neighbor]['local_intf'] + "</td>";
    console.log("description:" + data[key][neighbor]['description']);
    text+= "<td>" + data[key][neighbor]['description'] + "</td>";
    console.log("actual_bandwith:" + data[key][neighbor]['actual_bandwith']);
    text+= "<td>" + data[key][neighbor]['actual_bandwith'] + "</td>";

    text+= "</tr>";
  }

  text+= "</table>";

  return text;
}

// ####################################
// # using input parameters returns
// # HTML table with these inputs
// ####################################
function tableFromNeighbor(key,data){
  text = "<table class=\"infobox\">";
  text+= "<thead><th><u><h4>LOCAL INT.</h4></u></th><th><u><h4>NEIGHBOR</h4></u></th><th><u><h4>NEIGHBOR'S INT</h4></u></th>";
  text+= "</thead>";

  for (var neighbor in data[key]) {
    text+= "<tr>";

    var localport = data[key][neighbor]['local_intf'];
    console.log("local_intf:" + localport);
    text+= "<td><a href=\"javascript:LoadconfigdeviceHTML('"+key+"','"+devices[key]+"','"+localport+"');\">" + localport + "</a></td>";
    console.log("neighbor_intf:" + data[key][neighbor]['neighbor_intf']);
    text+= "<td>" + data[key][neighbor]['neighbor'] + "</td>";
    console.log("neighbor:" + data[key][neighbor]['neighbor']);
    text+= "<td>" + data[key][neighbor]['neighbor_intf'] + "</td>";

    text+= "</tr>";
  }

  text+= "</table>";

  return text;
}

// ####################################
// # replaces content of specified DIV
// ####################################
function printToDivWithID(id,text){
  div = document.getElementById(id);
  div.innerHTML = text;
}

function OnLinkMouseover(source, target, px, py, callback) {
    $.ajax({
	type:"GET",
	url: "/topology/linkdelay",
	dataType: "json",
	data: {'source':source, 'target':target},
	contentType: "application/json; charset=utf-8",
	success: function (data) {
		console.log("=============");
		console.log(data);
		console.log("=============");
		//displaylinkdelay(data[source]);
		value = data[source];
		callback(data[source], px, py);
		/*
		tooltip.html(data[source])
			.style("left",(d3.event.pageX)+"px")
			.style("top",(d3.event.pageY+20)+"px")
			.style("opacity",1.0);
		*/

	}
	});
}

// ########
// # MAIN #
// ########
var svg = d3.select("svg"),
    width  = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
    height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    
    d3.select("svg").attr("height",height)
    d3.select("svg").attr("width",width*0.7)  

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100).strength(0.001))
    .force("charge", d3.forceManyBody().strength(-200).distanceMax(500).distanceMin(50))
    .force("x", d3.forceX(function(d){
			if(d.group == "1"){
				return 5*(width*0.7)/6
			} else if (d.group == "2"){
				return 4*(width*0.7)/6
			} else if (d.group == "3"){
				return 3*(width*0.7)/6
			} else if (d.group == "4"){
				return 2*(width*0.7)/6  
			} else if (d.group == "5"){
				return 1*(width*0.7)/6                       
			} else {
				return 0*(width*0.7)/6 
			}
		 }).strength(1))
    .force("y", d3.forceY(height/2))
    .force("center", d3.forceCenter((width*0.7) / 2, height / 2))
    .force("collision", d3.forceCollide().radius(35));

var oldgraph = {
	links:[],
	nodes:[]
};

function checkaddlinks(newlinks) {

	if (newlinks == undefined)
		return;
	var len;
	len = newlinks.length;
	var len2 = oldgraph.links.length;
	var mape = new Array();

	if (len === 0) {
		oldgraph.links.length = 0;
		return;
	}
	for (let i=len -1; i >= 0; i--) {
		var find = 0;
		let j = 0;
		for (j = 0; j < len2; j++) {
			if ((newlinks[i].target == oldgraph.links[j].target.id) &&
				(newlinks[i].source == oldgraph.links[j].source.id)) {
				find = 1;
				break;
			}
		}
		//console.log(j);
		if (find === 0) {
			oldgraph.links.push(newlinks[i]);
		} else {
			mape.push(j);
		}
	}

	mape.sort(function sortNumber(a,b){return a - b	});

	for (let k = len2 - 1; k >= 0; k--) {
		if (mape.indexOf(k) === -1) {
			console.log("remove link");
			console.log( oldgraph.links[k]);
			oldgraph.links.splice(k, 1);
		}
	}
}

function checkaddnodes(newnodes) {

	var len;

	if (newnodes == undefined)
		return;

	len = newnodes.length;
	var len2 = oldgraph.nodes.length;
	var mape = new Array();

	if (len === 0) {
		oldgraph.nodes.length = 0;
	}
	for (let i=len - 1; i >= 0; i--) {
		var find = 0;
		let j = 0;
		for (j = 0; j < len2; j++) {
			if (newnodes[i].id == oldgraph.nodes[j].id) {
				find = 1;
				break;
			}
		}
		if (find == 0) {
			oldgraph.nodes.push(newnodes[i]);
		} else {
			//oldgraph.nodes.splice(j, 1);
			mape.push(j);
		}
	}

	mape.sort(function sortNumber(a,b){return a - b	});
	for (let k = len2 - 1; k >= 0 ; k--) {
		if (mape.indexOf(k) === -1) {
			console.log("remove node:");
			console.log(oldgraph.nodes[k]);
			oldgraph.nodes.splice(k, 1);
		}

	}
};



var tooltip = d3.select("body").append("div")
		.attr("class","tooltip")
		.attr("opacity",0.0);

var devices = new Array();

setInterval(function () {
	$.get("/getdevices", function(data, status) {
				console.log("-----------------");
				console.log(devices);
				devices = {};
				$.each(data, function(i, field){
					//console.log(field);
					devices[field.name] =  field.ip;
				});
	});

	$.get("topology/graph.json", function(rdata, status) {
	var rgraph = {
		links:[],
		nodes:[]
	};

	console.log("--------------------------");
	console.log(rdata);

	rgraph = rdata;
	
	console.log(rgraph);

	checkaddlinks(rgraph.links);
	checkaddnodes(rgraph.nodes);
	console.log(oldgraph);

	//To fix photo capture
	//TODO: disapear
	svg.selectAll("g").remove();

	var link = svg.selectAll("g.line")
			.data(oldgraph.links, function(d) {
				return d.source.id + "-" + d.target.id;
			})

	link.exit().remove();

	var node = svg.selectAll("g.a")
		.data(oldgraph.nodes)
	node.exit().remove();

	var linkadd = link.enter().append("g")
		.append("line")
		.attr("stroke", function(d) { return color(parseInt(d.value)); })
		.attr("stroke-width", function(d) { return Math.sqrt(parseInt(d.value)); })
		.attr("id", function(d){
				d.source.id + "-" + d.target.id;
			});

	linkadd.on("mouseover", function(d, i) {
		//alert(d.source.id)
		OnLinkMouseover(d.source.id, d.target.id, d3.event.pageX, d3.event.pageY, function(delayvalue, px, py){
			tooltip.html(delayvalue)
				.style("left",(px)+"px")
				.style("top",(py+20)+"px")
				.style("opacity",1.0);

		});
		console.log("mouse on line");

	});

	linkadd.on("mouseout", function(d, i){
		console.log("mouse out");
		tooltip.style("opacity",0.0)
			.transition()
			.duration(500);
	});

	var nodeadd = node.enter().append("g")
		.attr("class", "nodes")
		.append("a")
		.attr("target", '_blank')
		.attr("xlink:href",  function(d) { return (window.location.href + '?device=' + d.id) });

	nodeadd.on("click", function(d,i){ 
		d3.event.preventDefault();
		d3.event.stopPropagation();
		OnClickDetails(d.id);
		}
	);

	nodeadd.call(d3.drag()
	.on("start", dragstarted)
	.on("drag", dragged)
	.on("end", dragended));
  
	nodeadd.append("image")
		.attr("xlink:href", function(d) { return ("static/img/group" + d.group + ".png"); })
		.attr("width", 32)
		.attr("height", 32)
		.attr("x", - 16)
		.attr("y", - 16)
		.attr("fill", function(d) { return color(d.group); });
  
	nodeadd.append("text")
		.attr("font-size", "0.8em") 
		.attr("dx", 12)
		.attr("dy", ".35em")
		.attr("x", +8)
		.text(function(d) { return d.id });

	nodeadd.append("title")
		.text(function(d) { return d.id; });

	simulation
		.nodes(oldgraph.nodes)
		.on("tick", ticked);

	simulation.force("link")
		.links(oldgraph.links);

	simulation.alphaTarget(0.3).restart();

	function ticked() {
		linkadd
			.attr("x1", function(d) { return d.source.x; })
			.attr("y1", function(d) { return d.source.y; })
			.attr("x2", function(d) { return d.target.x; })
			.attr("y2", function(d) { return d.target.y; });

		nodeadd
			.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"});
	}
	});

}, 2000);

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

</script>

<script>
/*
  function LoadconfigdeviceHTML(n, i)
  {
	window.location.replace('/configdeviceHTML?name='+n+'&ip='+i);
  }

setInterval(function () {
		$.get("/getdevices", function(data, status) {
				console.log(data);
				document.getElementById("devices").innerHTML = "";
				$.each(data, function(i, field){
					$("#devices").append(function() {
						var refdev;
						refdev = "<li><a id=\"dev" + i + "\" href=\"javascript:LoadconfigdeviceHTML('"+field.name+"','"+field.ip+"');\">";
						refdev += field.name + "</a>";
						refdev += "</li><br>";
						console.log(refdev);
						return (refdev);
						});
				});
			}); 
}, 2000);

*/
</script>

